Input/Output devices
This week we learned more about programming microcontrollers, or rather Input/Output Devices in particular. There are digital and analog input devices. Most microcontrollers have a built-in Analog-to-Digital Converter (ADC) that converts analog signals into digital signals.
The assignment for this week involved using one analog input device, one digital input device, and two digital output devices. My idea was to use a button, a potentiometer, a servo motor, and a display. The potentiometer should set the angle for the servo, which is then displayed on the display. When the button is pressed, the angle is applied to the servo, and another message confirming this action is displayed on the display.
The code can be reviewed below; it is pretty self-explanatory:
#include <Adafruit_LiquidCrystal.h>
#include <Servo.h>
Adafruit_LiquidCrystal lcd(0);
Servo myServo;
// Constants for button and potentiometer pins
const int buttonPin = 2; // the number of the pushbutton pin
const int potPin = A0; // the number of the potentiometer pin
int potValue = 0; // variable to store the value coming from the potentiometer
int lastPotValue = -1; // variable to store the last potentiometer value
int angle = 0; // variable to store the servo position
bool buttonState = 0; // variable to store the button state
bool lastButtonState = 0; // variable to store the last button state
void setup()
{
myServo.attach(13, 500, 2500);
myServo.write(0); // set initial angle to 0° otherwise servo will default to 90°
lcd.begin(16, 2);
}
void loop()
{
// Read the potentiometer value
potValue = analogRead(potPin);
// Map it to a range from 0 to 180
angle = map(potValue, 0, 1023, 0, 180);
// Check if the potentiometer value has changed
if (potValue != lastPotValue)
{
// Display the current potentiometer value on the LCD
lcd.clear();
lcd.print("Value: ");
lcd.print(angle);
lastPotValue = potValue; // Update the last potentiometer value
}
// Read the button state
buttonState = digitalRead(buttonPin);
// Check if the button is pressed and was previously released
if (buttonState == LOW && lastButtonState == HIGH)
{
// Set the servo position
myServo.write(angle);
// Display that the value is set
lcd.setCursor(0, 1);
lcd.print("Set to: ");
lcd.print(angle);
}
// Save the current button state as the last button state
lastButtonState = buttonState;
// Delay a bit for debounce and to avoid flickering on the display
delay(100);
}
You can see the simulation in TinkerCAD here:
To run the code with the components we had in the lab, I had to make some adjustments. We used an RP2040-Zero again, as in our last blog post. The display I used required a different library and different functions for setup. I also had to use an additional 5V power supply because the microcontroller couldn't provide enough power to operate the servo. Another issue I encountered was that the display was flickering/updating frequently due to the potentiometer values fluctuating. To address this, I included a threshold that only updates the display when the change in value exceeds a certain limit.
You can checkout the new code below:
#include <LiquidCrystal_I2C.h>
#include <Servo.h>
#include <Wire.h>
LiquidCrystal_I2C lcd(0x27,16,2);
Servo myServo;
const int buttonPin = 0;
const int potPin = 26;
int potValue = 0;
int lastAngleValue = -1;
int angle = 0;
bool buttonState = 0;
bool lastButtonState = 0;
// Define a threshold value for updating the display
const int threshold = 5; // Adjust this value as needed
void setup()
{
myServo.attach(1, 500, 2500);
myServo.write(0);
Wire.setSDA(8);
Wire.setSCL(9);
lcd.init();
lcd.backlight();
}
void loop()
{
potValue = analogRead(potPin);
angle = map(potValue, 0, 1023, 0, 180);
// Check if the potentiometer value has changed significantly
if (abs(angle - lastAngleValue) > threshold)
{
// Only update the display if the change exceeds the threshold
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Value: ");
lcd.print(angle);
lastAngleValue = angle;
}
buttonState = digitalRead(buttonPin);
if (buttonState == LOW && lastButtonState == HIGH)
{
myServo.write(angle);
lcd.setCursor(0, 1);
lcd.print("Set to: ");
lcd.print(angle);
}
lastButtonState = buttonState;
// Delay a bit for debounce and to avoid flickering on the display
delay(100);
}
For the live demo watch this video: